package com.xiashitech.agent.db.dao.extload;

import cn.hutool.core.util.HashUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
// import com.xiashitech.agent.cache.authquery.extload.DesensitiseRuleLFUCache;
import com.xiashitech.agent.cache.authquery.extloadproxy.DesensitiseRuleLFUCacheProxy;
import com.xiashitech.agent.db.extload.LocalDataSource;
import com.xiashitech.agent.db.entity.DesensitiseRule;
import com.xiashitech.agent.dto.localdata.DesRuleDto;
import com.xiashitech.agent.utils.XSUtil;

import java.sql.SQLException;
import java.util.List;

public class DesensitiseRuleDao {

    public void truncate() throws SQLException{
        Db.use(LocalDataSource.getDS()).execute("TRUNCATE TABLE " + DesensitiseRule.TABLE_NAME);
    }

    public void saveInitData(List<DesRuleDto> dictList) {
        for (DesRuleDto dto : dictList){
            try {
                insert(dto.getRuleList());
            }catch (RuntimeException e){
                XSUtil.debug("ERROR [saveInitData]" + e.getMessage());
            }
        }
    }

    public void saveChangedData(List<DesRuleDto> dtoList) {
        // 兼容多表同时变更，但目前业务一次增量推送只有一个表
        for (DesRuleDto dto : dtoList){
            try {
                delete(dto.getSchemaName(), dto.getTableName());
                insert(dto.getRuleList());
            }catch (RuntimeException | SQLException e){
                XSUtil.debug("ERROR [saveChangedData]" + e.getMessage());
            }
        }
    }

    public void delete(String schemaName, String tableName) throws SQLException {
        Db.use(LocalDataSource.getDS()).del(
                Entity.create(DesensitiseRule.TABLE_NAME)
                        .set("SCHEMA_NAME", schemaName)
                        .set("TAB_NAME", tableName)
        );
    }

    public void insert(List<DesensitiseRule> ruleList) {
        //每次变更都是以表为单位推送，包含表当前状态下所有的脱敏配置。所以以表为单位删除、重建脱敏配置数据即可。
        // if the collection size > 1, it will execute in batches.
        //Db.use(LocalDataSource.getDS()).insert(entities);
        for (DesensitiseRule rule : ruleList){
            try {
                Entity entity = Entity.create(DesensitiseRule.TABLE_NAME).parseBean(rule, true, true);
                Db.use(LocalDataSource.getDS()).insert(entity);
            }catch (RuntimeException | SQLException e){
                XSUtil.debug("ERROR [insert]" + e.getMessage());
            }
        }

    }

    // 此查询为权限业务中的最高频查询业务，在这里做一个轻量缓存实现
    public List<DesensitiseRule> list(String schemaName, String tableName, String colName) throws SQLException {
        List<DesensitiseRule> desensitiseRuleList;
        String cacheKey = cacheKey(schemaName, tableName, colName);
        // Cache Get（考虑缓存穿透场景）
        if (DesensitiseRuleLFUCacheProxy.hasKey(cacheKey)){
            return DesensitiseRuleLFUCacheProxy.get(cacheKey);
        }
        String sql = "SELECT ID,TAB_NAME,COL_NAME,COL_NAME,IS_EXECUTE,API_PATH,PATCH_PATH,REGULAR,REPLACE_SYMBOL FROM DESENSITISE_RULE WHERE SCHEMA_NAME = ? AND TAB_NAME = ? AND COL_NAME = ?";
        desensitiseRuleList = Db.use(LocalDataSource.getDS()).query(sql, DesensitiseRule.class, schemaName, tableName, colName);
        // Cache Put
        DesensitiseRuleLFUCacheProxy.add(cacheKey, desensitiseRuleList);
        return desensitiseRuleList;
    }

    private String cacheKey(String schemaName, String tableName, String colName){
        String cacheKey = StrUtil.format("{}:{}:{}", schemaName, tableName, colName);
        return String.valueOf(HashUtil.apHash(cacheKey));
    }
    public void printAllDesensitiseRule(String soureFunction){
        try {
            String sql = "SELECT * FROM DESENSITISE_RULE";
            List<DesensitiseRule> desensitiseRuleList = Db.use(LocalDataSource.getDS()).query(sql, DesensitiseRule.class);
            long batchTs = System.nanoTime();
            if(desensitiseRuleList != null && desensitiseRuleList.size() > 0) {
                for (DesensitiseRule dr : desensitiseRuleList) {
                    System.out.println(Thread.currentThread().getId() + " T" + batchTs + " DesenseDebug, printAllDesensitiseRule, " + soureFunction + ": " + dr.toString());
                }
            } else {
                System.out.println(Thread.currentThread().getId() + " T" + batchTs + " DesenseDebug, printAllDesensitiseRule, " + soureFunction + ": desenserule size is 0");
            }
        }catch (SQLException e) {
            XSUtil.debug("SQL printAllDesensitiseRule ERROR: {}" + e.getMessage());
        }
    }

}
